package com.oanda.blackberry.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.InputConnection;

import net.rim.blackberry.api.invoke.Invoke;
import net.rim.blackberry.api.invoke.MessageArguments;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.Backlight;
import net.rim.device.api.system.CodeModuleManager;
import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.FontFamily;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.Status;
import net.rim.device.api.ui.container.MainScreen;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;

import com.oanda.blackberry.net.ConnectionManager;
import com.oanda.blackberry.net.RestException;
import com.oanda.blackberry.restapi.Account;
import com.oanda.blackberry.restapi.AccountEntry;
import com.oanda.blackberry.restapi.AccountStatus;
import com.oanda.blackberry.restapi.LimitOrderResponse;
import com.oanda.blackberry.restapi.Order;
import com.oanda.blackberry.restapi.OrderListResponse;
import com.oanda.blackberry.restapi.OrderPollResponse;
import com.oanda.blackberry.restapi.Position;
import com.oanda.blackberry.restapi.PositionsListResponse;
import com.oanda.blackberry.restapi.PricePoint;
import com.oanda.blackberry.restapi.Quote;
import com.oanda.blackberry.restapi.Rate;
import com.oanda.blackberry.restapi.RestThread;
import com.oanda.blackberry.restapi.Symbol;
import com.oanda.blackberry.restapi.Trade;
import com.oanda.blackberry.restapi.TradeListResponse;
import com.oanda.blackberry.restapi.TradeOrderResponse;
import com.oanda.blackberry.restapi.TradePollResponse;
import com.oanda.blackberry.restapi.User;
import com.oanda.blackberry.util.log.Logger;
import com.oanda.blackberry.view.OKDialogListener;
import com.oanda.blackberry.view.StatusView2;
import com.oanda.blackberry.view.SymbolsListField;

public class DefaultController extends AbstractController implements OKDialogListener {
    boolean isInterrupted = false;
    RestThread t;
    double bid = 1.23236D;
    double bid2 = 1.23236D;
    String quoteSymbol;
    int granularity;
    static Font componentFont;
    static Rate r;

    public void autoLogin() {
        UserSettings set = Model.getModel().getUserSettings(Model.getModel().getUrlIndex());
        if ((set != null) && (set.getUsernameLength() > 0) && (set.getPasswordLength() > 0)) {
            login(set.getUsername(), set.getSessionToken(), null);
        } else
            propertyChange(new PropertyChangeEvent(this, "showLogin", this, this));
    }

    public void onPlatformSelected(int platformIndex) {
        Model.getModel().setSelectedPlatformIndex(platformIndex);
    }

    private void showThrobber() {
        propertyChange(new PropertyChangeEvent(null, "showThrobber", null, null));
    }

    private void hideThrobber() {
        propertyChange(new PropertyChangeEvent(null, "hideThrobber", null, null));
    }

    public void submitRegistration(String userName, String password, String email,
            boolean isReceiveEmails) {
        showStatus("Registering");
        showThrobber();

        this.isInterrupted = false;

        this.t = new RestThread() {
            private String userName;
            private String password;
            private String email;
            private boolean isReceiveEmails;

            public void run() {
                boolean isError = false;
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                User user = new User();
                user.setUsername(this.userName);
                user.setPassword(this.password);
                user.setEmail(this.email);
                try {
                    String text = null;
                    text = user.register(this.userName, this.password, this.email,
                            this.isReceiveEmails);

                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                    DefaultController.this.setModelProperty("setRegistrationStatus", "");

                    DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                            "hideRegistration", null, null));
                    DefaultController.this.obtainSessionToken(this.userName, this.password, true);
                } catch (RestException ex) {
                    isError = true;
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.this.setModelProperty("setRegistrationStatus",
                                "Cancelled");
                    } else {
                        DefaultController.this.handleRestException(ex, "RegistrationException");
                    }
                } finally {
                    if (isError)
                        DefaultController.this.hideThrobber();
                }
            }
        };
        this.t.start();
    }

    public void register(String userName) {
        propertyChange(new PropertyChangeEvent(null, "showRegistration", null, null));
    }

    private void hideStatus() {
        setModelProperty("isStatusShown", new Boolean(false));
        setModelProperty("setStatusMessage", "");
    }

    public void sendOtp(String userName, String sessionToken) {
        showStatus("Requesting OTP...");

        showThrobber();
        this.isInterrupted = false;

        this.t = new RestThread() {
            private String userName;
            private String sessionToken;

            public void run() {
                boolean isError = false;

                User user = new User();
                try {
                    String text = null;

                    user.sendOtp(this.userName, this.sessionToken);

                    DefaultController.this.hideStatus();
                    DefaultController.this.hideThrobber();
                } catch (RestException ex) {
                    isError = true;
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.this.setModelProperty("setOtpStatus", "Cancelled");
                    } else {
                        DefaultController.this.handleRestException(ex, "SendOtpException");
                    }
                } finally {
                    if (isError)
                        DefaultController.this.hideThrobber();
                }
            }
        };
        this.t.start();
    }

    public void displayOtpHelp() {
        propertyChange(new PropertyChangeEvent(null, "showOtpHelpView", null, null));
    }

    public void obtainSessionToken(String userName, String password, boolean save) {
        showStatus("Logging in");
        showThrobber();

        if (save) {
            UserSettings settings = new UserSettings(Model.getModel().getUrlIndex(), userName,
                    password, save);
            setModelProperty("setUserSettings", settings);
        } else {
            UserSettings settings = new UserSettings(Model.getModel().getUrlIndex(), "", "", save);
            setModelProperty("setUserSettings", settings);
        }

        this.isInterrupted = false;

        this.t = new RestThread() {
            private String userName;
            private String password;

            public void run() {
                boolean isError = false;

                User user = new User();
                user.setUsername(this.userName);
                user.setPassword(this.password);

                DefaultController.this.setModelProperty("setUser", user);
                try {
                    String text = null;

                    User.OtpStatus otpStatus = user.discoverOtpStatus(this.userName, this.password);

                    DefaultController.this.hideStatus();

                    if ((isWorking()) && (otpStatus.sessionToken != null)
                            && (otpStatus.sessionToken.length() > 0)) {
                        DefaultController.this.setModelProperty("sessionToken",
                                otpStatus.sessionToken);
                    }
                } catch (RestException ex) {
                    isError = true;
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.this.setModelProperty("setStatusMessage", "Cancelled");
                    } else if (ex.getErrorMessage().indexOf("46: need otp") != -1) {
                        // TODO
                        DefaultController.this.showOtpView(this.userName, ex.getErrorMessage());
                    } else {
                        DefaultController.this.handleRestException(ex, "LoginException");
                    }
                } finally {
                    if (isError)
                        DefaultController.this.hideThrobber();
                }
            }
        };
        this.t.start();
    }

    private void showOtpView(String userName, String sessionToken) {
        propertyChange(new PropertyChangeEvent(null, "sessionTokenForOtp", null, sessionToken));
        propertyChange(new PropertyChangeEvent(null, "userName", null, userName));
        hideThrobber();
        hideStatus();
        propertyChange(new PropertyChangeEvent(null, "showOtpView", null, null));
    }

    private String extractSessionTokenFromError(String errorText) {
        return errorText.substring(errorText.indexOf("46: need otp") + 13);
    }

    private void handleRestException(RestException ex, String derivedExceptionId) {
        Logger.log("login ex:-" + String.valueOf(ex.getResponseCode()) + "-rm-"
                + ex.getReponseMessage() + "-em-" + ex.getErrorMessage() + "-");
        setModelProperty("setStatusMessage", "");
        propertyChange(new PropertyChangeEvent(null, derivedExceptionId, null, ex));

        if ((ex.getMessage().toLowerCase().indexOf("ioexception") > -1)
                && (ex.getMessage().toLowerCase().indexOf("invalid url parameter") > -1)) {
            showConnectionOptionsWarning(ex.getMessage());
        } else if ((ex.getMessage().toLowerCase().indexOf("ioexception") > -1)
                && (ex.getMessage().toLowerCase().indexOf("tunnel failed") > -1)) {
            showConnectionOptionsWarning(ex.getMessage());
        } else if (ex.getMessage().toLowerCase().indexOf("ioexception") > -1)
            showConnectionOptionsWarning(ex.getMessage());
    }

    public void login(String userName, String sessionToken, String otp) {
        showStatus("Logging in");
        showThrobber();
        propertyChange(new PropertyChangeEvent(null, "setRateQuoteStatus", null, "Logging in"));

        this.isInterrupted = false;

        this.t = new RestThread() {
            private String userName;
            private String sessionToken;
            private String otp;

            public void run() {
                boolean isError = false;

                User user = new User();
                try {
                    String text = null;

                    text = user.login(this.userName, this.sessionToken, this.otp);

                    JSONObject json = new JSONObject(text);
                    String sessionToken = json.getString("session_token");

                    DefaultController.this.hideStatus();

                    if ((isWorking()) && (sessionToken != null) && (sessionToken.length() > 0)) {
                        if (this.otp != null) {
                            DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                    "hideOtpView", null, null));
                        }
                        DefaultController.this.setModelProperty("sessionToken", sessionToken);
                    }
                } catch (RestException ex) {
                    isError = true;
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.this.setModelProperty("setStatusMessage", "Cancelled");
                    } else {
                        Logger.log("login ex:-" + String.valueOf(ex.getResponseCode()) + "-rm-"
                                + ex.getReponseMessage() + "-em-" + ex.getErrorMessage() + "-");
                        DefaultController.this.setModelProperty("setStatusMessage", "");
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "LoginException", null, ex));

                        if ((ex.getMessage().toLowerCase().indexOf("ioexception") > -1)
                                && (ex.getMessage().toLowerCase().indexOf("invalid url parameter") > -1)) {
                            DefaultController.this.showConnectionOptionsWarning(ex.getMessage());
                        } else if ((ex.getMessage().toLowerCase().indexOf("ioexception") > -1)
                                && (ex.getMessage().toLowerCase().indexOf("tunnel failed") > -1)) {
                            DefaultController.this.showConnectionOptionsWarning(ex.getMessage());
                        } else if (ex.getMessage().toLowerCase().indexOf("ioexception") > -1)
                            DefaultController.this.showConnectionOptionsWarning(ex.getMessage());
                    }
                } catch (JSONException localJSONException) {
                } finally {
                    if (isError)
                        DefaultController.this.hideThrobber();
                }
            }
        };
        this.t.start();
    }

    public void logout(String sessionToken) {
        showStatus("logging out");
        this.isInterrupted = false;

        Model.getModel().getSettings().setAccount(null);
        Rate.setSince(0L);

        propertyChange(new PropertyChangeEvent(null, "hideThrobber", null, null));

        setModelProperty("sessionToken", "");
        setModelProperty("setStatusMessage", "");

        propertyChange(new PropertyChangeEvent(null, "hideRatesView", null, ""));
        show();

        this.t = new RestThread() {
            private String sessionToken;

            public void run() {
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                User user = new User();
                try {
                    String text = null;
                    text = user.logout(this.sessionToken);
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                    }
                } catch (IOException localIOException) {
                } finally {
                }
            }
        };
        this.t.start();
    }

    public void accountList(String sessionToken, String username) {
        if (sessionToken == null) {
            inform("serious error occured! (1)");
            return;
        }

        if ((Model.getModel().getSettings() != null)
                && (Model.getModel().getSettings().getAccount() != null)
                && (Model.getModel().getAccount().getAccountEntrys() != null)) {
            Logger.log("getting account from the cache");
            setModelProperty("setAccount", Model.getModel().getSettings().getAccount());
            return;
        }

        Logger.log("DefaultController accountList(final String sessionToken)");

        showStatus("accountList");

        this.isInterrupted = false;
        setModelProperty("setStatusMessage", " getting accounts list");
        propertyChange(new PropertyChangeEvent(this, "setRateQuoteStatus", null,
                " getting accounts list"));

        propertyChange(new PropertyChangeEvent(null, "setRequestMethod", null, "accountList"));

        this.t = new RestThread() {
            private String sessionToken;
            private String username;

            public void run() {
                boolean isError = false;
                Account account = new Account();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = account.list(this.sessionToken, this.username);
                    JSONObject json = new JSONObject(text);

                    Logger.log(json.toString());

                    JSONArray accountList = json.getJSONArray("account_list");

                    if ((accountList != null) && (accountList.length() > 0)) {
                        AccountEntry[] entry = new AccountEntry[accountList.length()];
                        for (int i = 0; i < accountList.length(); i++) {
                            JSONObject object = accountList.getJSONObject(i);
                            entry[i] = new AccountEntry(String.valueOf(object.getInt("id")),
                                    object.getString("name"), object.getString("homecurr"),
                                    String.valueOf(object.getDouble("margin_rate")));
                        }

                        if (entry.length == 1) {
                            entry[0].setActive(true);
                        }

                        account.setAccountEntrys(entry);
                    } else {
                        DefaultController.inform("Unable to get account info");
                    }

                    if (isWorking()) {
                        Logger.log("account list is here. set model property");
                        DefaultController.this.setModelProperty("setStatusMessage", "");
                        DefaultController.this.setModelProperty("setAccount", account);
                    }
                } catch (RestException ex) {
                    isError = true;
                    if (ex != null)
                        Logger.log("accountList ex:-" + ex.getErrorMessage() + "-"
                                + ex.getReponseMessage());
                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    }
                } catch (JSONException ex) {
                    Runnable r;
                    DefaultController
                            .inform("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    if (isError) {
                        Runnable r = new Runnable() {
                            public void run() {
                                int i = Dialog.ask(3, "Retry?", 4);
                                if (i == 4)
                                    DefaultController.this.accountList(sessionToken, username);
                            }
                        };
                        DefaultController.this.invokeLater(r);
                    } else {
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "setRequestMethod", null, ""));
                    }
                }
            }
        };
        this.t.start();
    }

    public void accountStatus(String accountId, String sessionToken) {
        Logger.log("DefaultController accountStatus" + accountId + " " + sessionToken);

        if ((sessionToken == null) || (accountId == null)) {
            return;
        }

        showStatus("accountStatus");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", " getting account details for account(" + accountId
                + ")...");

        propertyChange(new PropertyChangeEvent(null, "setRequestMethod", null, "accountStatus"));
        this.t = new RestThread() {
            private String accountId;
            private String sessionToken;

            public void run() {
                boolean isError = false;
                String errorMessage = null;

                Account account = Model.getModel().getAccount();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = account.status(this.accountId, this.sessionToken);

                    JSONObject json = new JSONObject(text);
                    Logger.log(json.toString());

                    JSONObject accountStatus = json;

                    if ((accountStatus != null) && (accountStatus.length() > 0)) {
                        AccountStatus aStatus = new AccountStatus();
                        aStatus.setBalance(accountStatus.getDouble("balance"));
                        aStatus.setId(String.valueOf(accountStatus.getInt("account_id")));
                        aStatus.setMargin_avail(accountStatus.getDouble("margin_avail"));
                        aStatus.setMargin_used(accountStatus.getDouble("margin_used"));
                        aStatus.setNav(accountStatus.getDouble("nav"));
                        aStatus.setOpen_orders(accountStatus.getInt("open_orders"));
                        aStatus.setOpen_trades(accountStatus.getInt("open_trades"));
                        aStatus.setRealized_pl(accountStatus.getDouble("realized_pl"));
                        aStatus.setUnrealized_pl(accountStatus.getDouble("unrealized_pl"));

                        DefaultController.this.setModelProperty("setStatusMessage", "");
                        if (isWorking())
                            DefaultController.this.setModelProperty("setAccountStatus", aStatus);
                    } else {
                        DefaultController.inform("accountStatus object is invalid");
                    }
                } catch (RestException ex) {
                    isError = true;
                    if (ex != null)
                        Logger.log("accountStatus ex:-" + ex.getErrorMessage() + "-"
                                + ex.getReponseMessage());
                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        errorMessage = ex.getMessage();
                    }
                } catch (JSONException ex) {
                    DefaultController
                            .inform("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                            "accountStatusFinished", null, ""));
                    if (isError) {
                        DefaultController.this.setModelProperty("setErrorMessage",
                                " getting account details for account(" + this.accountId + ")...");

                        DefaultController.this.accountStatus(this.accountId, this.sessionToken);
                    } else {
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "setRequestMethod", null, ""));
                    }
                }
            }
        };
        this.t.start();
    }

    public void quote(String sessionToken, String symbols, String timestamp) {
        Logger.log("DefaultController quote:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        showStatus("quote");
        this.isInterrupted = false;

        if (timestamp == null) {
            propertyChange(new PropertyChangeEvent(this, "setRateQuoteStatus", null,
                    " refreshing..."));
        }
        this.t = new RestThread() {
            private String sessionToken;
            private String symbols;
            private String timestamp;

            public void run() {
                boolean isError = false;
                String errorMessage = "";
                Rate rates = new Rate();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = rates.quote(this.sessionToken, this.symbols, this.timestamp);

                    JSONObject json = new JSONObject(text);

                    JSONArray pricesArray = json.getJSONArray("prices");

                    if ((pricesArray != null) && (pricesArray.length() > 0)) {
                        Quote[] quotes = new Quote[pricesArray.length()];
                        for (int i = 0; i < pricesArray.length(); i++) {
                            JSONObject object = pricesArray.getJSONObject(i);
                            quotes[i] = new Quote(object.getString("symbol"),
                                    object.getLong("time"), object.getDouble("bid"),
                                    object.getDouble("ask"));

                            Rate.setSince(quotes[i].getTime());
                        }
                        rates.setQuotes(quotes);

                        if (isWorking()) {
                            DefaultController.this.setModelProperty("setRateQuote", rates);
                        }

                    } else if (Model.getModel().getRateQuotes() == null) {
                        DefaultController
                                .inform("Unable to parse the result(quote list is empty).");
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "RatesException", null, "Error in parsing result."));
                    }
                } catch (RestException ex) {
                    isError = true;
                    if (ex != null)
                        Logger.log("quote ex:-" + ex.getErrorMessage() + "-"
                                + ex.getReponseMessage());
                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("access denied") > -1)) {
                        errorMessage = ex.getErrorMessage();
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        errorMessage = ex.getMessage();
                        if (this.timestamp == null)
                            DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                    "setRateQuoteStatus", null, DefaultController.this
                                            .getNiceErrormessage(errorMessage)));
                    }
                } catch (JSONException ex) {
                    isError = true;
                    errorMessage = "Unable to parse the result(" + ex.getMessage() + ").";
                    Logger.log(errorMessage);
                } finally {
                    if (!isError) {
                        if ((Model.getModel().getSettings().getRate().getSymbols() != null)
                                && (Model.getModel().getSettings().getRate().getSymbols().length > 0)) {
                            DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                    "removeRateQuoteStatus", null, ""));
                        }
                    } else if ((errorMessage != null)
                            && (errorMessage.toLowerCase().indexOf("access denied") < 0)
                            && (this.timestamp == null))
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "RatesException", null, DefaultController.this
                                        .getNiceErrormessage(errorMessage)));
                }
            }
        };
        this.t.start();
    }

    public void quoteAll(String sessionToken, String symbols, String timestamp) {
        Logger.log("DefaultController quoteAll:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        showStatus("quote");
        this.isInterrupted = false;

        propertyChange(new PropertyChangeEvent(this, "setMenuStatus", null, " refreshing quotes..."));

        propertyChange(new PropertyChangeEvent(null, "setRequestMethod", null, "quoteAll"));

        this.t = new RestThread() {
            private String sessionToken;
            private String symbols;
            private String timestamp;

            public void run() {
                Rate rates = new Rate();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = rates.quote(this.sessionToken, this.symbols, this.timestamp);

                    JSONObject json = new JSONObject(text);

                    JSONArray pricesArray = json.getJSONArray("prices");

                    if ((pricesArray != null) && (pricesArray.length() > 0)) {
                        Quote[] quotes = new Quote[pricesArray.length()];
                        for (int i = 0; i < pricesArray.length(); i++) {
                            JSONObject object = pricesArray.getJSONObject(i);
                            quotes[i] = new Quote(object.getString("symbol"),
                                    object.getLong("time"), object.getDouble("bid"),
                                    object.getDouble("ask"));

                            rates.setSinceAll(quotes[i].getTime());
                        }
                        rates.setQuotesAll(quotes);
                        if (isWorking())
                            DefaultController.this.setModelProperty("setRateQuoteAll", rates);
                    } else {
                        DefaultController
                                .inform("Unable to parse the result(quote array is empty).");
                    }
                } catch (RestException ex) {
                    if (ex != null)
                        Logger.log("quote ex:-" + ex.getErrorMessage() + "-"
                                + ex.getReponseMessage());
                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        DefaultController.inform("Error:"
                                + ex.getMessage().substring(ex.getMessage().indexOf(' ')));
                    }
                } catch (JSONException ex) {
                    DefaultController
                            .inform("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                            "removeMenuStatus", null, ""));
                }
            }
        };
        this.t.start();
    }

    public void tradeList(String optMaxTradeId, String optMaxCount, String optSymbol,
            String optTradeIds) {
        String sessionToken = Model.getModel().getSessionToken();
        String accountId = Model.getModel().getActiveAccountId();
        Logger.log("DefaultController tradeList:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            inform("no session tocken");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            inform("Please, select an active account from accounts menu");
            return;
        }

        showStatus("tradeList");
        this.isInterrupted = false;

        propertyChange(new PropertyChangeEvent(this, "setTradeListStatus", null,
                "Retrieving trades from server..."));

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;
            private String optMaxTradeId;
            private String optMaxCount;
            private String optSymbol;
            private String optTradeIds;

            public void run() {
                boolean isError = false;
                String errorMessage = "";

                Trade trade = new Trade();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = trade.list(this.sessionToken, this.accountId, this.optMaxTradeId,
                            this.optMaxCount, this.optSymbol, this.optTradeIds);

                    JSONObject json = new JSONObject(text);

                    JSONArray tradesArray = json.getJSONArray("open_trades");

                    if ((tradesArray != null) && (tradesArray.length() > 0)) {
                        Logger.log("trades array: " + tradesArray.toString());
                        Logger.log("length: " + String.valueOf(tradesArray.length()));

                        TradeListResponse[] tradeList = null;
                        Vector v = new Vector();
                        long max = Trade.maxTradeId;

                        for (int i = 0; i < tradesArray.length(); i++) {
                            JSONObject object = tradesArray.getJSONObject(i);
                            if (object == null)
                                continue;
                            Logger.log(object.toString());
                            TradeListResponse tlr = new TradeListResponse(object.getLong("id"),
                                    object.getInt("units"), object.getString("dir"),
                                    object.getString("symbol"), object.getLong("time"),
                                    object.getDouble("price"), object.getDouble("stop_loss"),
                                    object.getDouble("take_profit"),
                                    object.getDouble("trailing_stop"));

                            if (max < tlr.getId()) {
                                max = tlr.getId();
                            }
                            if (tlr.getSymbol().startsWith("XXX"))
                                continue;
                            v.addElement(tlr);
                        }

                        if ((v != null) && (v.size() > 0)) {
                            tradeList = new TradeListResponse[v.size()];

                            for (int i = 0; i < v.size(); i++) {
                                TradeListResponse object = (TradeListResponse) v.elementAt(i);
                                tradeList[i] = object;
                            }
                        }

                        if (isWorking()) {
                            Trade.setMaxTradeId(max);
                            DefaultController.this.setModelProperty("setTradeList", tradeList);
                        }
                    } else {
                        DefaultController.this.setModelProperty("setTradeList", null);
                    }
                } catch (RestException ex) {
                    isError = true;

                    if ((ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().indexOf("access denied") > -1)) {
                        isError = false;
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        errorMessage = ex.getMessage();
                    }
                } catch (JSONException ex) {
                    isError = true;
                    errorMessage = "Unable to parse the result(" + ex.getMessage() + ").";
                } finally {
                    DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                            "removeTradeListStatus", null, ""));
                    if (isError)
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "TradeListException", null, DefaultController.this
                                        .getNiceErrormessage(errorMessage)));
                }
            }
        };
        this.t.start();
    }

    public void tradePoll() {
        String sessionToken = Model.getModel().getSessionToken();
        String accountId = Model.getModel().getActiveAccountId();
        Logger.log("DefaultController tradePoll:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            inform("no session token");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            inform("Please, select an active account from accounts menu");
            return;
        }

        if (Trade.getMaxTradeId() == 0L)
            ;
        showStatus("tradePoll");
        this.isInterrupted = false;

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;

            public void run() {
                boolean isError = false;
                Trade trade = new Trade();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = trade.poll(this.sessionToken, this.accountId,
                            Long.toString(Trade.getMaxTradeId()));

                    JSONObject json = new JSONObject(text);

                    JSONArray closedArray = json.getJSONArray("closed");
                    JSONArray updatedArray = json.getJSONArray("updated");
                    JSONArray openedArray = json.getJSONArray("opened");
                    long max = json.getLong("max_trade_id");

                    TradePollResponse response = new TradePollResponse();
                    response.setMaxTradeId(max);

                    if ((closedArray != null) && (closedArray.length() > 0)) {
                        long[] closed = new long[closedArray.length()];
                        for (int i = 0; i < closedArray.length(); i++) {
                            closed[i] = closedArray.getLong(i);
                        }
                        response.setClosed(closed);
                    }
                    if ((updatedArray != null) && (updatedArray.length() > 0)) {
                        long[] updated = new long[updatedArray.length()];
                        for (int i = 0; i < updatedArray.length(); i++) {
                            updated[i] = updatedArray.getLong(i);
                        }
                        response.setUpdated(updated);
                    }

                    if ((openedArray != null) && (openedArray.length() > 0)) {
                        long[] opened = new long[openedArray.length()];
                        for (int i = 0; i < openedArray.length(); i++) {
                            opened[i] = openedArray.getLong(i);
                        }
                        response.setOpened(opened);
                    }

                    if (isWorking())
                        DefaultController.this.setModelProperty("setTradePollResponse", response);
                } catch (RestException ex) {
                    isError = true;
                    if ((ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                    } else
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "setTradeListError", null, DefaultController.this
                                        .getNiceErrormessage(ex.getMessage())));
                } catch (JSONException ex) {
                    isError = true;
                    DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                            "setTradeListError", null, DefaultController.this
                                    .getNiceErrormessage(ex.getMessage())));
                } finally {
                    if (!isError)
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "removeTradeListStatus", null, ""));
                }
            }
        };
        this.t.start();
    }

    public void orderPoll() {
        String sessionToken = Model.getModel().getSessionToken();
        String accountId = Model.getModel().getActiveAccountId();
        Logger.log("DefaultController orderPoll:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            inform("no session token");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            inform("Please, select an active account from accounts menu");
            return;
        }

        if (Order.getMaxOrderId() == 0L)
            ;
        showStatus("orderPoll");
        this.isInterrupted = false;

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;

            public void run() {
                boolean isError = false;
                Order order = new Order();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = order.poll(this.sessionToken, this.accountId,
                            Long.toString(Order.getMaxOrderId()));

                    JSONObject json = new JSONObject(text);

                    JSONArray deletedArray = json.getJSONArray("deleted");
                    JSONArray updatedArray = json.getJSONArray("updated");
                    JSONArray createdArray = json.getJSONArray("created");
                    long max = json.getLong("max_order_id");

                    OrderPollResponse response = new OrderPollResponse();
                    response.setMaxOrderId(max);

                    if ((deletedArray != null) && (deletedArray.length() > 0)) {
                        long[] closed = new long[deletedArray.length()];
                        for (int i = 0; i < deletedArray.length(); i++) {
                            closed[i] = deletedArray.getLong(i);
                        }
                        response.setDeleted(closed);
                    }
                    if ((updatedArray != null) && (updatedArray.length() > 0)) {
                        long[] updated = new long[updatedArray.length()];
                        for (int i = 0; i < updatedArray.length(); i++) {
                            updated[i] = updatedArray.getLong(i);
                        }
                        response.setUpdated(updated);
                    }

                    if ((createdArray != null) && (createdArray.length() > 0)) {
                        long[] opened = new long[createdArray.length()];
                        for (int i = 0; i < createdArray.length(); i++) {
                            opened[i] = createdArray.getLong(i);
                        }
                        response.setCreated(opened);
                    }

                    if (isWorking()) {
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "setOrderListStatus", null, ""));
                        DefaultController.this.setModelProperty("setOrderPollResponse", response);
                    }
                } catch (RestException ex) {
                    isError = true;
                    if ((ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                    } else
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "setOrderListError", null, DefaultController.this
                                        .getNiceErrormessage(ex.getMessage())));
                } catch (JSONException ex) {
                    isError = true;
                    DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                            "setOrderListError", null, DefaultController.this
                                    .getNiceErrormessage(ex.getMessage())));
                } finally {
                    if (!isError)
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "removeOrderListStatus", null, ""));
                }
            }
        };
        this.t.start();
    }

    public void listSymbols(String sessionToken) {
        Logger.log("DefaultController listSymbol:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            inform("serious promlem occured! (error: 2)");
            return;
        }

        boolean getItFromFile = false;

        if ((Model.getModel().getSettings().getRate().getSymbols() == null)
                || ((Model.getModel().getSettings().getRate().getSymbols() == null) && (Model
                        .getModel().getSettings().getRate().getSymbols().length > 0))) {
            getItFromFile = true;
        }

        showStatus("rates");
        this.isInterrupted = false;
        if (!getItFromFile) {
            setModelProperty("setStatusMessage", "getting symbols...");
            propertyChange(new PropertyChangeEvent(this, "setRateQuoteStatus", null,
                    "getting symbols..."));
        }

        boolean getItFromFileF = getItFromFile;
        this.t = new RestThread() {
            private boolean getItFromFileF;
            private String sessionToken;

            public void run() {
                boolean isError = false;

                Rate rates = new Rate();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;

                    if (!this.getItFromFileF) {
                        text = rates.listSymbols(this.sessionToken);
                    } else {
                        text = DefaultController.loadSymbolsFromFile();
                    }

                    JSONObject json = new JSONObject(text);

                    JSONArray symbolsArray = json.getJSONArray("symbols");

                    if ((symbolsArray != null) && (symbolsArray.length() > 0)) {
                        Symbol[] symbols = null;
                        Vector v = new Vector();
                        for (int i = 0; i < symbolsArray.length(); i++) {
                            JSONObject object = symbolsArray.getJSONObject(i);
                            Symbol s = new Symbol(object.getString("symbol"),
                                    object.getInt("precision"), object.getDouble("piploc"),
                                    Symbol.autoCheckActiveDefaultList(object.getString("symbol")));

                            if (s.getSymbol().startsWith("XXX"))
                                continue;
                            v.addElement(s);
                        }

                        if ((v != null) && (v.size() > 0)) {
                            symbols = new Symbol[v.size()];

                            for (int i = 0; i < v.size(); i++) {
                                Symbol object = (Symbol) v.elementAt(i);
                                symbols[i] = object;
                            }
                        }

                        rates.setSymbols(symbols);
                        if (isWorking()) {
                            DefaultController.this.setModelProperty("setRateSymbol", rates);
                        }
                    }
                } catch (RestException ex) {
                    isError = true;

                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    }
                } catch (JSONException ex) {
                    isError = true;
                    Logger.log("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    if (!this.getItFromFileF) {
                        DefaultController.this.setModelProperty("setStatusMessage", "");

                        if (isError) {
                            DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                    "setErrorMessage", null, "retrying..."));
                            DefaultController.this.listSymbols(this.sessionToken);
                        }
                    } else {
                        DefaultController.this.updateSymbols(this.sessionToken);
                    }
                }
            }
        };
        this.t.start();
    }

    public void updateSymbols(String sessionToken) {
        Logger.log("DefaultController updateSymbol:  " + sessionToken);

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        this.isInterrupted = false;
        this.t = new RestThread() {
            private String sessionToken;

            public void run() {
                boolean isError = false;

                Rate rates = new Rate();
                try {
                    String text = null;
                    text = rates.listSymbols(this.sessionToken);

                    JSONObject json = new JSONObject(text);

                    JSONArray symbolsArray = json.getJSONArray("symbols");

                    if ((symbolsArray != null) && (symbolsArray.length() > 0)) {
                        Symbol[] symbols = null;
                        Vector v = new Vector();
                        int i = 0;
                        for (int j = 0; i < symbolsArray.length(); i++) {
                            JSONObject object = symbolsArray.getJSONObject(i);
                            Symbol s = new Symbol(object.getString("symbol"),
                                    object.getInt("precision"), object.getDouble("piploc"),
                                    Symbol.autoCheckActiveDefaultList(object.getString("symbol")));

                            if (s.getSymbol().startsWith("XXX"))
                                continue;
                            v.addElement(s);
                        }

                        if ((v != null) && (v.size() > 0)) {
                            symbols = new Symbol[v.size()];

                            for (int j = 0; j < v.size(); j++) {
                                Symbol object = (Symbol) v.elementAt(j);
                                symbols[j] = object;
                            }
                        }
                        SymbolsListField.alphaSort(symbols);
                        rates.setSymbols(symbols);
                        if (isWorking())
                            DefaultController.this.setModelProperty("setRateSymbol", rates);
                    }
                } catch (RestException ex) {
                    DefaultController.this.updateSymbols(this.sessionToken);
                } catch (JSONException ex) {
                    DefaultController.this.updateSymbols(this.sessionToken);
                } finally {
                }
            }
        };
        this.t.start();
    }

    public void useAccount(String accountId) {
        setModelProperty("useAccount", accountId);
    }

    public void useSymbol(String symbol, boolean active) {
        if (active)
            setModelProperty("useSymbol", symbol);
        else
            setModelProperty("notUseSymbol", symbol);
    }

    public void trustAll(boolean checked) {
        setModelProperty("trustAll", new Boolean(checked));
    }

    public void enableHttpsRedirect(boolean checked) {
        setModelProperty("enableHttpsRedirect", new Boolean(checked));
    }

    public void endToEndRequired(boolean checked) {
        setModelProperty("endToEndRequired", new Boolean(checked));
    }

    public void userUrl(int index) {
        if (index != -1)
            setModelProperty("setUrlIndex", new Integer(index));
    }

    public void setConnectionSuffixIndex(int index) {
        if (index != -1)
            setModelProperty("setConnectionSuffixIndex", new Integer(index));
    }

    public void show() {
        Logger.log("show");
        propertyChange(new PropertyChangeEvent(this, "showLogin", this, this));
    }

    public void pushScreen(MainScreen s) {
        if (s == null) {
            Logger.log("DefaultController.pushScreen: screen is null.");
            return;
        }

        if (s.isDisplayed()) {
            Logger.log("DefaultController.pushScreen: screen is displayed.");

            return;
        }
        Logger.log("DefaultController.pushScreen: " + s);
        UiApplication ui = UiApplication.getUiApplication();
        if (!ui.hasEventThread()) {
            Logger.log("hasEventThread false ");
            ui.pushScreen(s);
        } else {
            ui.invokeLater(new Runnable() {
                private MainScreen s;
                private UiApplication ui;

                public void run() {
                    if (this.s != null) {
                        if ((UiApplication.getUiApplication().getActiveScreen() != null)
                                && (!UiApplication.getUiApplication().getActiveScreen()
                                        .equals(this.s)))
                            this.ui.pushScreen(this.s);
                    } else
                        DefaultController.inform("controller push screen s  is null");
                }
            });
        }
    }

    public void popScreen(MainScreen s) {
        if (s == null) {
            Logger.log("pop screen: null");
            return;
        }
        Logger.log("pop screen: " + s.toString());
        UiApplication ui = UiApplication.getUiApplication();
        ui.invokeLater(new Runnable() {
            private UiApplication ui;
            private MainScreen s;

            public void run() {
                try {
                    this.ui.popScreen(this.s);
                } catch (IllegalArgumentException iae) {
                    Logger.log("tried to pop a screen that is not on display stack"
                            + iae.getMessage());
                }
            }
        });
    }

    public void invokeLater(Runnable r) {
        UiApplication ui = UiApplication.getUiApplication();
        ui.invokeLater(r);
    }

    public static void inform(String message) {
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            private String message;

            public void run() {
                Status.show(this.message);
            }
        });
    }

    public static void inform(String message, int secconds) {
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            private String message;
            private int secconds;

            public void run() {
                Status.show(this.message, this.secconds * 1000);
            }
        });
    }

    public static void showMessage(String message) {
        String _message = message;
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            private String _message;

            public synchronized void run() {
                StatusView2.showInfoDialog(this._message);
            }
        });
    }

    public void showStatus(String statusText) {
        setModelProperty("setStatusMessage", statusText);
    }

    public void performAction(Object o) {
        if ((o instanceof Boolean)) {
            if (((Boolean) o).booleanValue()) {
                this.isInterrupted = true;
                if (this.t != null) {
                    this.t.stopConn();
                }
                setModelProperty("isStatusShown", new Boolean(false));
            }
        }
    }

    public void exit() {
        Logger.log("Controler exit()");
        Model.getModel().getSettings().commit();

        System.exit(0);
    }

    public void help() {
        StatusView2.showYesNoDialog("Contact us to email problems?", new OKDialogListener() {
            public void performAction(Object o) {
                if (((o instanceof Boolean)) && (((Boolean) o).booleanValue())) {
                    String to = "frontdesk@oanda.com";
                    String subject = "Oanda BlackBerry Application Help Request";
                    String body = DefaultController.this.getInformation();
                    new Thread(new Runnable() {
                        private String body;

                        public void run() {
                            Invoke.invokeApplication(2, new MessageArguments("new",
                                    "frontdesk@oanda.com",
                                    "Oanda BlackBerry Application Help Request", this.body));
                        }
                    }).start();
                }
            }
        });
    }

    public void about() {
        inform("@TODO About Text");
    }

    public void showOptions() {
        propertyChange(new PropertyChangeEvent(this, "showOptionsView", this, this));
    }

    public void updateQuote() {
        if (ConnectionManager.getUrl().startsWith("device")) {
            Rate rates = new Rate();
            Quote[] quotes = new Quote[3];

            quotes[0] = new Quote("EUR/USD", 1234567890L, this.bid, 1.23457D);
            quotes[1] = new Quote("USD/CAD", 1234567890L, this.bid2, 1.23457D);
            quotes[2] = new Quote("XAU/USD", 1234567890L, this.bid, 1.23237D);
            rates.setQuotes(quotes);
            setModelProperty("setRateQuote", rates);
        } else {
            Model.getModel().getRate();
            long l = Rate.getSince();
            String timeStamp = null;
            if (l > 0L) {
                timeStamp = Long.toString(l);
            }

            String symbols = Model.getModel().getRateSymbolsSelected();
            if ((symbols != null) && (symbols.length() < 3)) {
                symbols = Symbol.getDefaultSymbolsList();
                listSymbols(Model.getModel().getSessionToken());
            }

            quote(Model.getModel().getSessionToken(), symbols, timeStamp);
        }
    }

    public void updateQuotesAll() {
        if (ConnectionManager.getUrl().startsWith("device")) {
            Rate rates = new Rate();
            Quote[] quotes = new Quote[3];
            this.bid += 0.0013D;
            this.bid2 -= 0.0013D;
            quotes[0] = new Quote("EUR/USD", 1234567890L, this.bid, 1.23457D);
            quotes[1] = new Quote("USD/CAD", 1234567890L, this.bid2, 1.23457D);
            quotes[2] = new Quote("XAU/USD", 1234567890L, this.bid, 1.23457D);
            rates.setQuotes(quotes);
            setModelProperty("setRateQuote", rates);
        } else {
            long l = Model.getModel().getRate().getSinceAll();
            String timeStamp = null;
            if (l > 0L) {
                timeStamp = Long.toString(l);
            }
            quoteAll(Model.getModel().getSessionToken(), Model.getModel().getRateSymbolsAll(),
                    timeStamp);
        }
    }

    public void sell(Quote quote) {
        setModelProperty("newSellTradeOpen", quote);
    }

    public void buy(Quote quote) {
        if (quote != null)
            quote.setBuy(true);
        setModelProperty("newBuyTradeOpen", quote);
    }

    public void updateHistory() {
        String sessionToken = Model.getModel().getSessionToken();

        if ((sessionToken == null) || (this.quoteSymbol == null)) {
            return;
        }

        showStatus("quote");
        this.isInterrupted = false;

        this.t = new RestThread() {
            private String sessionToken;

            public void run() {
                Rate rates = new Rate();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = rates.historyUpdate(this.sessionToken,
                            DefaultController.this.quoteSymbol, DefaultController.this.granularity,
                            1);

                    JSONObject json = new JSONObject(text);

                    JSONArray pricesArray = json.getJSONArray("price_points");

                    if ((pricesArray != null) && (pricesArray.length() > 0)) {
                        PricePoint[] points = new PricePoint[pricesArray.length()];
                        for (int i = 0; i < pricesArray.length(); i++) {
                            JSONObject object = pricesArray.getJSONObject(i);
                            points[i] = new PricePoint(object.getLong("time"),
                                    (float) object.getDouble("open_bid"),
                                    (float) object.getDouble("open_ask"),
                                    (float) object.getDouble("close_bid"),
                                    (float) object.getDouble("close_ask"),
                                    (float) object.getDouble("max_bid"),
                                    (float) object.getDouble("max_ask"),
                                    (float) object.getDouble("min_bid"),
                                    (float) object.getDouble("min_ask"));
                        }

                        rates.setPricePoints(points);
                        if (isWorking())
                            DefaultController.this.setModelProperty("setRateHistoryUpdate", rates);
                    } else {
                        DefaultController
                                .inform("Unable to parse the result(quote array is empty).");
                    }
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    }
                } catch (JSONException localJSONException) {
                } finally {
                }
            }
        };
        this.t.start();
    }

    public void history(Quote quote, int granularity, int points) {
        String sessionToken = Model.getModel().getSessionToken();

        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        if (quote == null) {
            Logger.log("quote is null");
            return;
        }

        propertyChange(new PropertyChangeEvent(null, "historySymbol", null, quote.getSymbol()));
        Symbol s = Model.getModel().getSymbol(quote.getSymbol());
        if (s != null) {
            propertyChange(new PropertyChangeEvent(null, "historyPrecious", null, new Integer(
                    s.getPrecision())));
        }

        propertyChange(new PropertyChangeEvent(null, "historyQuote", null, quote));

        this.quoteSymbol = quote.getSymbol();
        this.granularity = granularity;

        showStatus("quote");

        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "getting history...");
        propertyChange(new PropertyChangeEvent(null, "setHistoryUpdateStatus", null,
                "getting history..."));
        propertyChange(new PropertyChangeEvent(null, "showThrobber", null, null));

        this.t = new RestThread() {
            private String sessionToken;
            private Quote quote;
            private int granularity;
            private int points;

            public void run() {
                boolean isError = false;
                String errorMessage = "";
                Rate rates = new Rate();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    byte[] b = rates.history(this.sessionToken, this.quote.getSymbol(),
                            this.granularity, this.points);

                    JSONObject json = new JSONObject(new String(b));

                    JSONArray pricesArray = json.getJSONArray("price_points");

                    if ((pricesArray != null) && (pricesArray.length() > 0)) {
                        PricePoint[] points = new PricePoint[pricesArray.length()];
                        for (int i = 0; i < pricesArray.length(); i++) {
                            JSONObject object = pricesArray.getJSONObject(i);
                            points[i] = new PricePoint(object.getLong("time"),
                                    (float) object.getDouble("open_bid"),
                                    (float) object.getDouble("open_ask"),
                                    (float) object.getDouble("close_bid"),
                                    (float) object.getDouble("close_ask"),
                                    (float) object.getDouble("max_bid"),
                                    (float) object.getDouble("max_ask"),
                                    (float) object.getDouble("min_bid"),
                                    (float) object.getDouble("min_ask"));
                        }

                        rates.setPricePoints(points);
                        if (isWorking())
                            DefaultController.this.setModelProperty("setRateHistory", rates);
                    } else {
                        isError = true;
                        errorMessage = "Unable to parse the result(quote array is empty).";
                        Logger.log(errorMessage);
                    }
                } catch (RestException ex) {
                    isError = true;
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        errorMessage = "Error:"
                                + ex.getMessage().substring(ex.getMessage().indexOf(' '));
                        DefaultController.this
                                .setModelProperty("setStatusMessage", ex.getMessage());
                    }
                } catch (JSONException ex) {
                    errorMessage = "Unable to parse the result(" + ex.getMessage() + ").";
                } finally {
                    if (!isError) {
                        DefaultController.this.setModelProperty("setStatusMessage", "");
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "removeHistoryUpdateStatus", null, ""));
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "hideThrobber", null, null));
                    } else {
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "HistoryException", null, DefaultController.this
                                        .getNiceErrormessage(errorMessage)));
                    }
                }
            }
        };
        this.t.start();
    }

    public void tradeOrder(String symbol, String units, String accountid, String type,
            String price, String lowPrice, String highPrice, String stopLoss, String takeProfit,
            String trailingStop) {
        String sessionToken = Model.getModel().getSessionToken();
        Logger.log("DefaultController tradeOrder:  " + sessionToken);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        showStatus("trade order");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "creating trade");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private String symbol;
            private String units;
            private String accountid;
            private String type;
            private String price;
            private String lowPrice;
            private String highPrice;
            private String stopLoss;
            private String takeProfit;
            private String trailingStop;

            public void run() {
                Trade trade = new Trade();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = trade.order(this.sessionToken, this.symbol, this.units, this.accountid,
                            this.type, this.price, this.lowPrice, this.highPrice, this.stopLoss,
                            this.takeProfit, this.trailingStop);

                    JSONObject json = new JSONObject(text);

                    String symbol = json.optString("symbol");
                    int units = json.optInt("units");
                    double price = json.getDouble("price");
                    double margin = json.getDouble("margin_used");
                    String dir = json.optString("dir");

                    TradeOrderResponse response = new TradeOrderResponse(symbol, units, price,
                            margin, dir);

                    if (isWorking())
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "setTradeOrderResponse", null, response));
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("access denied") > -1)) {
                        DefaultController
                                .showMessage("Your session timed out. The quote might be changed. Go back to the previous screen and reexecute your order.");
                    } else {
                        DefaultController.inform("Error:"
                                + ex.getMessage().substring(ex.getMessage().indexOf(' ')));
                    }
                } catch (JSONException ex) {
                    DefaultController
                            .inform("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public void newOrder(String accountid, String symbol, String units, String price,
            String expiry, String optType, String optLowerPrice, String optHighPrice,
            String optStopLoss, String optTakeProfit, String optTrailingStop) {
        String sessionToken = Model.getModel().getSessionToken();
        Logger.log("DefaultController tradeOrder:  " + sessionToken);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        showStatus("new order");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "creating order");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private String accountid;
            private String symbol;
            private String units;
            private String price;
            private String expiry;
            private String optType;
            private String optLowerPrice;
            private String optHighPrice;
            private String optStopLoss;
            private String optTakeProfit;
            private String optTrailingStop;

            public void run() {
                Order order = new Order();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = order.create(this.sessionToken, this.accountid, this.symbol, this.units,
                            this.price, this.expiry, this.optType, this.optLowerPrice,
                            this.optHighPrice, this.optStopLoss, this.optTakeProfit,
                            this.optTrailingStop);

                    JSONObject json = new JSONObject(text);

                    int id = json.getInt("id");
                    int units = json.optInt("units");
                    double price = json.getDouble("price");
                    String symbol = json.optString("symbol");
                    String dir = json.optString("dir");

                    LimitOrderResponse response = new LimitOrderResponse(id, units, price, symbol,
                            dir);

                    if (isWorking())
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "setNewLimitOrderResponse", null, response));
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("access denied") > -1)) {
                        DefaultController
                                .showMessage("Your session timed out. The quote might be changed. Go back to the previous screen and reexecute your order.");
                    } else {
                        DefaultController.inform("Error:"
                                + ex.getMessage().substring(ex.getMessage().indexOf(' ')));
                    }
                } catch (JSONException ex) {
                    DefaultController
                            .inform("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public void positionsList() {
        String sessionToken = Model.getModel().getSessionToken();
        String accountId = Model.getModel().getActiveAccountId();
        Logger.log("DefaultController positionsList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        showStatus("positions list");
        this.isInterrupted = false;
        propertyChange(new PropertyChangeEvent(this, "setTradeListStatus", null,
                "Retrieving positions from server..."));

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;

            public void run() {
                boolean isError = false;
                String errorMessage = "";
                Position positions = new Position();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = positions.list(this.sessionToken, this.accountId);

                    JSONObject json = new JSONObject(text);

                    JSONArray positionsArray = json.getJSONArray("open_positions");

                    if ((positionsArray != null) && (positionsArray.length() > 0)) {
                        PositionsListResponse[] pos = null;
                        Vector v = new Vector();
                        for (int i = 0; i < positionsArray.length(); i++) {
                            JSONObject object = positionsArray.getJSONObject(i);
                            PositionsListResponse plr = new PositionsListResponse(
                                    object.getString("dir"), object.getString("symbol"),
                                    object.getInt("units"), object.getDouble("avg_price"));

                            if (plr.getSymbol().startsWith("XXX"))
                                continue;
                            v.addElement(plr);
                        }

                        if ((v != null) && (v.size() > 0)) {
                            pos = new PositionsListResponse[v.size()];

                            for (int i = 0; i < v.size(); i++) {
                                PositionsListResponse object = (PositionsListResponse) v
                                        .elementAt(i);
                                pos[i] = object;
                            }
                        }

                        if (isWorking())
                            DefaultController.this.setModelProperty("setPositionsList", pos);
                    } else {
                        DefaultController.this.setModelProperty("setTradeList", null);
                    }
                } catch (RestException ex) {
                    isError = true;
                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().indexOf("access denied") > -1)) {
                        isError = false;
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        errorMessage = ex.getMessage();
                    }
                } catch (JSONException ex) {
                    isError = true;
                    errorMessage = "Unable to parse the result(" + ex.getMessage() + ").";
                } finally {
                    DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                            "removeTradeListStatus", null, ""));
                    if (isError)
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "TradeListException", null, errorMessage));
                }
            }
        };
        this.t.start();
    }

    public void orderList(String optMaxOrderId, String optMaxCount, String optSymbol,
            String optOrdersList) {
        String sessionToken = Model.getModel().getSessionToken();

        String accountId = Model.getModel().getActiveAccountId();

        Logger.log("DefaultController orderList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            showMessage("session problem!");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        showStatus("order list");
        this.isInterrupted = false;
        propertyChange(new PropertyChangeEvent(this, "setOrderListStatus", null,
                "Retrieving orders from server..."));

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;
            private String optMaxOrderId;
            private String optMaxCount;
            private String optSymbol;
            private String optOrdersList;

            public void run() {
                boolean isError = false;
                String errorMessage = "";

                Order orders = new Order();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = orders.list(this.sessionToken, this.accountId, this.optMaxOrderId,
                            this.optMaxCount, this.optSymbol, this.optOrdersList);

                    JSONObject json = new JSONObject(text);

                    JSONArray positionsArray = json.getJSONArray("open_orders");

                    if ((positionsArray != null) && (positionsArray.length() > 0)) {
                        Vector p = new Vector();

                        long max = Order.maxOrderId;
                        for (int i = 0; i < positionsArray.length(); i++) {
                            JSONObject object = positionsArray.getJSONObject(i);
                            String type = object.getString("type");

                            if ((type == null)
                                    || ((!type.equals("BuyStop")) && (!type.equals("SellStop"))
                                            && (!type.equals("BuyLimit"))
                                            && (!type.equals("SellLimit"))
                                            && (!type.equals("BuyEntry")) && (!type
                                            .equals("SellEntry")))) {
                                continue;
                            }

                            OrderListResponse el = new OrderListResponse(object.getInt("id"),
                                    object.getString("type"), object.getString("symbol"),
                                    object.getInt("units"), object.getLong("time"),
                                    object.getDouble("price"), object.getDouble("stop_loss"),
                                    object.getDouble("take_profit"), object.getLong("expiry"),
                                    object.getDouble("high_limit"), object.getDouble("low_limit"),
                                    object.getDouble("trailing_stop"));

                            if (max < el.getId()) {
                                max = el.getId();
                            }
                            if (el.getSymbol().startsWith("XXX"))
                                continue;
                            p.addElement(el);
                        }

                        Logger.log("to array");
                        OrderListResponse[] pos = null;
                        if ((p != null) && (p.size() > 0)) {
                            pos = new OrderListResponse[p.size()];

                            for (int i = 0; i < p.size(); i++) {
                                OrderListResponse object = (OrderListResponse) p.elementAt(i);
                                pos[i] = object;
                            }
                        }
                        Logger.log("set resoinse");
                        if (isWorking()) {
                            Order.setMaxOrderId(max);
                            DefaultController.this.setModelProperty("setStatusMessage", "");
                            DefaultController.this.setModelProperty("setOrderList", pos);
                        }
                    } else {
                        DefaultController.this.setModelProperty("setOrderList", null);
                    }
                } catch (RestException ex) {
                    isError = true;

                    if ((ex != null) && (ex.getResponseCode() == 403)
                            && (ex.getReponseMessage().toLowerCase().indexOf("forbidden") > -1)
                            && (ex.getErrorMessage().indexOf("access denied") > -1)) {
                        DefaultController.this.autoLogin();
                    } else if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        errorMessage = ex.getMessage();
                    }
                } catch (JSONException ex) {
                    isError = true;
                    errorMessage = "Unable to parse the result(" + ex.getMessage() + ").";
                } finally {
                    DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                            "removeOrderListStatus", null, ""));
                    if (isError)
                        DefaultController.this.propertyChange(new PropertyChangeEvent(this,
                                "OrderListException", null, DefaultController.this
                                        .getNiceErrormessage(errorMessage)));
                }
            }
        };
        this.t.start();
    }

    public void viewOrderDetails(OrderListResponse orderListSelected) {
        propertyChange(new PropertyChangeEvent(this, "showOrderDetailsView", null, this));

        if (orderListSelected != null)
            propertyChange(new PropertyChangeEvent(this, "setOrderDetails", null, orderListSelected));
    }

    public void viewTradeDetails(Object[] tradeDetails) {
        propertyChange(new PropertyChangeEvent(null, "showTradesDetailsView", null, this));
        if ((tradeDetails != null) && (tradeDetails.length == 2)
                && ((tradeDetails[0] instanceof TradeListResponse))
                && ((tradeDetails[1] instanceof Quote))) {
            propertyChange(new PropertyChangeEvent(null, "setTradesDetails", null,
                    (TradeListResponse) tradeDetails[0]));
            propertyChange(new PropertyChangeEvent(null, "setTradesDetailsQuote", null,
                    (Quote) tradeDetails[1]));
        }
    }

    public void cancelTrade(TradeListResponse tradeListSelected) {
        String sessionToken = Model.getModel().getSessionToken();

        String accountId = Model.getModel().getActiveAccountId();

        Logger.log("DefaultController orderList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            showMessage("session problem!");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        showStatus("close trade");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "closing trade");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private TradeListResponse tradeListSelected;
            private String accountId;

            public void run() {
                Trade trade = new Trade();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = trade.close(this.sessionToken,
                            String.valueOf(this.tradeListSelected.getId()), this.accountId, null);

                    JSONObject json = new JSONObject(text);

                    String id = Long.toString(json.getLong("id"));
                    String message = "Trade: " + id + " closed(price: "
                            + Double.toString(json.getDouble("price")) + ", profit: "
                            + Double.toString(json.getDouble("profit")) + ", "
                            + json.getString("symbol") + ")";

                    if (isWorking()) {
                        String idDeleted = Long.toString(this.tradeListSelected.getId());
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "tradeClosed", null, idDeleted));
                        DefaultController.showMessage(message);
                        DefaultController.this.propertyChange(new PropertyChangeEvent("",
                                "hideTradesDetailsView", null, ""));
                    }
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else if ((ex != null)
                            && (ex.getResponseCode() == 400)
                            && (ex.getReponseMessage().toLowerCase().indexOf("bad request") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("invalid trade id") > -1)) {
                        DefaultController
                                .inform("The selected trade might have already been closed.");
                    } else {
                        DefaultController.inform(ex.getMessage());
                    }
                } catch (JSONException localJSONException) {
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public void cancelOrder(OrderListResponse orderListSelected) {
        if (orderListSelected == null) {
            Logger.log("DefaultController cancelOrder is null");
            return;
        }
        String sessionToken = Model.getModel().getSessionToken();

        String accountId = Model.getModel().getActiveAccountId();

        Logger.log("DefaultController orderList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            showMessage("session problem!");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        showStatus("close order");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "closing order");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;
            private OrderListResponse orderListSelected;

            public void run() {
                Order order = new Order();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = order.delete(this.sessionToken, this.accountId,
                            String.valueOf(this.orderListSelected.getId()));

                    JSONObject json = new JSONObject(text);

                    String id = String.valueOf(json.getInt("id"));
                    String message = "Order: " + id + " closed(price: "
                            + Double.toString(json.getDouble("price")) + ", "
                            + json.getString("symbol") + ").";

                    if (isWorking()) {
                        DefaultController.this
                                .propertyChange(new PropertyChangeEvent(null, "orderClosed", null,
                                        String.valueOf(this.orderListSelected.getId())));

                        DefaultController.showMessage(message);
                        DefaultController.this.propertyChange(new PropertyChangeEvent("",
                                "hideOrdersDetailsView", null, ""));
                    }
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else if ((ex != null)
                            && (ex.getResponseCode() == 400)
                            && (ex.getReponseMessage().toLowerCase().indexOf("bad request") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("invalid order id") > -1)) {
                        DefaultController
                                .inform("The selected order might have already been closed.");
                    } else {
                        DefaultController.inform(ex.getMessage());
                    }
                } catch (JSONException localJSONException) {
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public void cancelPosition(PositionsListResponse tradeListSelected) {
        String sessionToken = Model.getModel().getSessionToken();

        String accountId = Model.getModel().getActiveAccountId();

        Logger.log("DefaultController orderList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            showMessage("session problem!");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        showStatus("close trade");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "closing position");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private String accountId;
            private PositionsListResponse tradeListSelected;

            public void run() {
                Position trade = new Position();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = trade.close(this.sessionToken, this.accountId,
                            this.tradeListSelected.getSymbol(), null);

                    JSONObject json = new JSONObject(text);

                    String symbol = json.getString("symbol");
                    String message = "Position: " + symbol + " closed(price: "
                            + Double.toString(json.getDouble("price")) + ", total units: "
                            + String.valueOf(json.getInt("total_units")) + ")";

                    if (isWorking()) {
                        DefaultController.this.propertyChange(new PropertyChangeEvent(null,
                                "positionsClosed", null, symbol));
                        DefaultController.showMessage(message);
                    }
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else if ((ex != null) && (ex.getResponseCode() == 400)
                            && (ex.getReponseMessage().toLowerCase().indexOf("bad request") > -1)
                            && (ex.getErrorMessage().toLowerCase().indexOf("invalid ") > -1)) {
                        DefaultController
                                .inform("The selected position might have already been closed.");
                    } else {
                        DefaultController.inform(ex.getMessage());
                    }
                } catch (JSONException localJSONException) {
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public void changeTrade(String tradeId, String accountId, String optStopLoss,
            String optTakeProfit, String optTrailingStop) {
        String sessionToken = Model.getModel().getSessionToken();

        Logger.log("DefaultController orderList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            showMessage("session problem!");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        if ((tradeId == null) || ((tradeId != null) && (tradeId.length() == 0))) {
            showMessage("Undefined trade!");
            return;
        }

        showStatus("change trade");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "changing trade");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private String tradeId;
            private String accountId;
            private String optStopLoss;
            private String optTakeProfit;
            private String optTrailingStop;

            public void run() {
                Trade trade = new Trade();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = null;
                    text = trade.change(this.sessionToken, this.tradeId, this.accountId,
                            this.optStopLoss, this.optTakeProfit, this.optTrailingStop);

                    JSONObject json = new JSONObject(text);

                    if (isWorking()) {
                        DefaultController.showMessage("Trade " + this.tradeId + " changed!");

                        DefaultController.this.propertyChange(new PropertyChangeEvent("",
                                "hideTradesDetailsView", null, ""));

                        DefaultController.this.orderList(null, "1", null, this.tradeId);
                    }
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        DefaultController.inform("Error:"
                                + ex.getMessage().substring(ex.getMessage().indexOf(' ')));
                    }
                } catch (JSONException ex) {
                    DefaultController
                            .inform("Unable to parse the result(" + ex.getMessage() + ").");
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public void changeOrder(String orderId, String accountId, String symbol, String type,
            String units, String price, String expiry, String optLowPrice, String optHighPrice,
            String optStopLoss, String optTakeProfit, String optTrailingStop) {
        String sessionToken = Model.getModel().getSessionToken();

        Logger.log("DefaultController orderList:  " + sessionToken + " " + accountId);
        if ((sessionToken == null) || ((sessionToken != null) && (sessionToken.length() == 0))) {
            showMessage("session problem!");
            return;
        }

        if ((accountId == null) || ((accountId != null) && (accountId.length() == 0))) {
            showMessage("Please, select an active account from accounts menu");
            return;
        }

        if ((orderId == null) || ((orderId != null) && (orderId.length() == 0))) {
            showMessage("Undefined order!");
            return;
        }
        if ((orderId == null) || ((orderId != null) && (orderId.length() == 0))) {
            showMessage("Undefined order!");
            return;
        }
        if ((symbol == null) || ((symbol != null) && (symbol.length() == 0))) {
            showMessage("Undefined symbol!");
            return;
        }
        if ((type == null) || ((type != null) && (type.length() == 0))) {
            showMessage("Undefined type!");
            return;
        }
        if ((units == null) || ((units != null) && (units.length() == 0))) {
            showMessage("Undefined units!");
            return;
        }
        if ((price == null) || ((price != null) && (price.length() == 0))) {
            showMessage("Undefined price!");
            return;
        }
        if ((expiry == null) || ((expiry != null) && (expiry.length() == 0))) {
            showMessage("Undefined expiry!");
            return;
        }

        showStatus("change order");
        this.isInterrupted = false;
        setModelProperty("setStatusMessage", "changing order");
        setModelProperty("isStatusShown", new Boolean(true));

        this.t = new RestThread() {
            private String sessionToken;
            private String orderId;
            private String accountId;
            private String symbol;
            private String type;
            private String units;
            private String price;
            private String expiry;
            private String optLowPrice;
            private String optHighPrice;
            private String optStopLoss;
            private String optTakeProfit;
            private String optTrailingStop;

            public void run() {
                Order order = new Order();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException ex) {
                }
                try {
                    String text = order.change(this.sessionToken, this.orderId, this.accountId,
                            this.symbol, this.type, this.units, this.price, this.expiry,
                            this.optLowPrice, this.optHighPrice, this.optStopLoss,
                            this.optTakeProfit, this.optTrailingStop);

                    if (isWorking()) {
                        DefaultController.showMessage("Order changed");

                        DefaultController.this.propertyChange(new PropertyChangeEvent("",
                                "hideOrdersDetailsView", null, ""));
                    }
                } catch (RestException ex) {
                    if (DefaultController.this.isInterrupted) {
                        DefaultController.this.isInterrupted = false;
                        DefaultController.inform("Cancelled");
                    } else {
                        DefaultController.inform("Error:"
                                + ex.getMessage().substring(ex.getMessage().indexOf(' ')));
                    }
                } finally {
                    DefaultController.this.setModelProperty("isStatusShown", new Boolean(false));
                }
            }
        };
        this.t.start();
    }

    public static Font getComponentFont() {
        if (componentFont == null) {
            try {
                FontFamily ff = FontFamily.forName("BBAlpha Sans");
                Font defaultFont = ff.getFont(0, 20);

                componentFont = defaultFont;
            } catch (ClassNotFoundException n) {
                componentFont = Font.getDefault().derive(0, 20);
            }

        }

        return componentFont;
    }

    public static Font getComponentFont(int size) {
        Font f = null;
        try {
            FontFamily ff = FontFamily.forName("BBAlpha Sans");
            f = ff.getFont(0, size);
        } catch (ClassNotFoundException n) {
            f = Font.getDefault().derive(0, size);
        }

        return f;
    }

    public static Font getComponentFontTall(int size) {
        Font f = null;
        try {
            FontFamily ff = FontFamily.forName("BBMillbankTall");
            f = ff.getFont(1, size);
        } catch (ClassNotFoundException n) {
            f = Font.getDefault().derive(0, size);
        }

        return f;
    }

    public void setHistoryChartTypeIndex(int historyChartTypeIndex) {
        setModelProperty("setHistoryChartTypeIndex", new Integer(historyChartTypeIndex));
    }

    public void setHistoryTimeInterval(String historyTimeInterval) {
        setModelProperty("setHistoryTimeInterval", historyTimeInterval);
    }

    public void turnOnBacklight() {
        if ((Display.getProperties() & 0x4000) != 0)
            Backlight.enable(true, Backlight.getTimeoutDefault());
    }

    public void turnOnBacklight(int seconds) {
        if ((Display.getProperties() & 0x4000) != 0)
            Backlight.enable(true, seconds);
    }

    public void turnLED() {
    }

    public void showInternetTrafficWarning() {
        if (Model.getModel().isShowInternetTrafficWarning())
            StatusView2
                    .showInfoDialog(
                            "This application consumes much Internet traffic. You are able to change your connection type from options menu",
                            new OKDialogListener() {
                                public void performAction(Object o) {
                                    if (((o instanceof Boolean)) && (((Boolean) o).booleanValue()))
                                        Model.getModel().setShowInternetTrafficWarning(false);
                                }
                            });
    }

    public void showConnectionOptionsWarning(String optionalErrorMessage) {
        String warning = "Unable to connect. Probably the selected networking connection path is not available. You may change your connection type from \"Options\" menu( "
                + optionalErrorMessage + ")";
        StatusView2.showInfoDialog(warning);
    }

    public String getNiceErrormessage(String error) {
        String niceErrorMessage = "Operation failed.";

        if (error == null)
            return niceErrorMessage;

        error = error.toLowerCase();

        if (error.indexOf("ioexception") > -1) {
            if (error.indexOf("connection closed") > -1)
                niceErrorMessage = "";
            else if (error.indexOf("tcp read time out") > -1)
                niceErrorMessage = "";
            else if (error.indexOf("timed out") > -1)
                niceErrorMessage = "";
            else if (error.indexOf("connection timed out") > -1) {
                niceErrorMessage = "";
            }

        } else if ((error != null) && (error.indexOf("interruptedioexception") > -1)) {
            if (error.indexOf("local connection timed out after") > -1)
                niceErrorMessage = "";
        } else if (error.indexOf("access denied") > -1) {
            return "";
        }

        return niceErrorMessage;
    }

    public static String loadSymbolsFromFile() {
        StringBuffer b = new StringBuffer();
        try {
            InputConnection fileConnection = (InputConnection) Connector
                    .open("cod://oanda/list_symbols.json.bin");
            InputStream fin = null;
            fin = fileConnection.openInputStream();
            if (fin == null) {
                return null;
            }

            int i = 0;
            while ((i = fin.read()) != -1)
                b.append((char) i);
        } catch (Exception ex) {
            return null;
        }

        return b.toString();
    }

    public static Symbol getStaticSymbol(String name) {
        if (r == null)
            try {
                String text = loadSymbolsFromFile();
                JSONObject json = new JSONObject(text);

                JSONArray symbolsArray = json.getJSONArray("symbols");

                if ((symbolsArray != null) && (symbolsArray.length() > 0)) {
                    Symbol[] symbols = new Symbol[symbolsArray.length()];
                    for (int i = 0; i < symbolsArray.length(); i++) {
                        JSONObject object = symbolsArray.getJSONObject(i);
                        symbols[i] = new Symbol(object.getString("symbol"),
                                object.getInt("precision"), object.getDouble("piploc"),
                                Symbol.autoCheckActiveDefaultList(object.getString("symbol")));
                    }

                    r = new Rate();
                    r.setSymbols(symbols);
                    r.sortSymbols();

                    return r.getSymbol(name);
                }
            } catch (JSONException e) {
                return null;
            }
        else {
            return r.getSymbol(name);
        }

        return null;
    }

    private String getInformation() {
        StringBuffer b = new StringBuffer();
        b.append("\n-----------------------");
        b.append("\nVersion: ");
        Model.getModel();
        b.append(Model.getVERSION());
        b.append("\nPIN: ");
        b.append(Integer.toHexString(DeviceInfo.getDeviceId()).toUpperCase());
        b.append("\nDevice name: ");
        b.append(DeviceInfo.getDeviceName());

        b.append("\nOperating system: ");
        b.append(getPlatformVersion());
        b.append("\nPlatform name: ");
        b.append(DeviceInfo.getDeviceName());
        b.append("\nManufacture name: ");
        b.append(DeviceInfo.getManufacturerName());
        b.append("\n-----------------------\n");
        return b.toString();
    }

    public static String getPlatformVersion() {
        if (!DeviceInfo.isSimulator()) {
            ApplicationManager appMan = ApplicationManager.getApplicationManager();

            ApplicationDescriptor[] appDes = appMan.getVisibleApplications();

            int size = appDes.length;

            for (int i = size - 1; i >= 0; i--) {
                if (appDes[i].getModuleName().equals("net_rim_bb_ribbon_app")) {
                    return appDes[i].getVersion();
                }

            }

            int[] handles = CodeModuleManager.getModuleHandles();

            size = handles.length;

            for (int i = size - 1; i >= 0; i--) {
                if (CodeModuleManager.getModuleName(handles[i]).equals("net_rim_bb_ribbon_app")) {
                    return CodeModuleManager.getModuleVersion(handles[i]);
                }
            }
        }
        return "";
    }
}
